#ifndef _IM_SERVER_HTTP_REQUEST_
#define _IM_SERVER_HTTP_REQUEST_

#include <string>
#include <vector>
#include <iostream>
#include <map>
#include <ostream>

#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>

#include "im/common/common.h"
#include "comet_connection.h"

namespace imserver {

class ImMessage;

enum SERVER_RSP_TYPE {
  LOGIN_SUCCESS = 1,
  LOGIN_FAIL    = 2,
  SESSION_CONFLICT = 3,
  IM_MESSAGE    = 4,
  IM_MESSAGE_GROUP = 5,
  SEND_SUCCESS  = 6,
  SEND_FAIL     = 7,
  FORBIDDEN     = 8,
  PARAM_ERROR   = 9,
  DUPLICATE_SUBSCRIBER = 10,
  ACCESS_SWITCH = 11
};


class HttpRequest : public boost::enable_shared_from_this<HttpRequest> {
 public:
  static bool IsHeaderCompleted(const char * data, size_t len);
  friend std::ostream& operator << (HttpRequest & req, std::ostream& os);

  HttpRequest(CometConnectionPtr conn, const std::string & data);
  virtual ~HttpRequest();

  virtual void OnReadError() {}
  void OnReadComplete(); // 非虚函数, 覆盖Response()可以改变其行为 

  virtual void OnWriteError() {}
  virtual void OnWriteComplete() {}

  virtual int OnCheckTicketComplete(int64_t qid, const std::string & username) { return 0; }
  virtual int DuplicateErrorResponse() { return 0; }
  virtual int UnauthorizedResponse();
  virtual int OnMessageReady(const std::vector<ImMessage> &messages) { return 0; }

  size_t AppendBody(const char * data, size_t len);

  bool IsLegal() const;

  bool IsBodyCompleted() const {
    if (method_ == "POST" && body_.size() < content_length()) { 
      return false;
    }
    return true;
  }

  const std::string & method() const {
    return method_;
  }
  const std::string & url() const {
    return url_;
  }
  
  size_t content_length() const;

  const std::string & cookie(const std::string& key) const {
    std::map<std::string, std::string>::const_iterator it = cookies_.find(key);
    if (it != cookies_.end()) {
      return it->second;
    }
    static std::string empty;
    return empty;
  }

  const std::string & query_param(const std::string& key) const {
    std::map<std::string, std::string>::const_iterator it = query_params_.find(key);
    if (it != query_params_.end()) {
      return it->second;
    }
    static std::string empty;
    return empty;
  }

  const std::string & post_param(const std::string& key) const {
    std::map<std::string, std::string>::const_iterator it = post_params_.find(key);
    if (it != post_params_.end()) {
      return it->second;
    }
    static std::string empty;
    return empty;
  }

  static std::string CalculateSession(int64_t uid, const std::string & q_ticket, const std::string & t_ticket);


  std::string remote_addr() const {
    return connection_->remote_addr();
  }
  void Abort();

  int64_t effective_uid() {
    return qid_ > 0 ? qid_ : temp_id_;
  }

 protected:
  int CheckTicket();
  std::string IdCookiesHeader(int64_t qid,
      const std::string & qid_ticket,
      int64_t temp_id,
      const std::string & temp_id_ticket);
  std::string ParseCallback();

  CometConnectionPtr connection_;
  std::string method_;
  std::string url_;
  std::string query_;
  std::map<std::string, std::string> query_params_;
  std::map<std::string, std::string> post_params_;
  std::string version_;
  std::map<std::string, std::string> headers_;
  std::string body_;

  std::map<std::string, std::string> cookies_;

  std::string effective_session() {
    return qid_ > 0 ? qid_ticket_ : temp_id_ticket_;
  }

  int64_t qid_;
  std::string qid_ticket_;
  int64_t temp_id_;
  std::string temp_id_ticket_;

  // TODO : 改善性能
  std::string response_;
 private:
  virtual bool Response() = 0;
};

std::ostream& operator<<(HttpRequest & req, std::ostream& os);

}

#endif // _IM_SERVER_HTTP_REQUEST_
